<template>
  <BasicModal ref="modalRef" destroyOnClose wrapClassName="j-cgform-tab-modal" v-bind="$attrs" @register="registerModal" :width="modalWidth" :centered="true" :footer="null">
    <!-- 标题区域 -->
    <template #title>
      <div class="titleArea">
        <div class="title">{{ title }}</div>
        <div class="right">
          <a-radio-group v-model:value="activeKey">
            <template v-for="(item, index) in tabNav" :key="index">
              <a-radio-button :value="item.tableName">{{ item.tableTxt }}</a-radio-button>
            </template>
          </a-radio-group>
        </div>
      </div>
    </template>
    <!--表单区域 -->
    <div class="contentArea">
      <!--主表区域 -->
      <BasicForm @register="registerForm" ref="formRef" v-show="activeKey == refKeys[0]" name="FollowUpForm" />
      <div v-if="activeKey == 'followUp' && !formDisabled" style="text-align: right; margin: 0">
        <a-button type="primary" @click="MainTableSubmit()" style="height: 32px">确认</a-button>
      </div>
      <!--子表区域 -->
      <template v-if="activeKey == 'followPlan'">
        <div class="btn-row-flex">
          <template v-if="!formDisabled">
            <a-button type="primary" @click="showAddPlanModal = true" style="height: 32px; border-radius: 8px; box-shadow: 0 2px 8px #e6f7ff">新增跟进计划</a-button>
            <a-button type="primary" @click="MainTableSubmit()" style="height: 32px">确认</a-button>
          </template>
        </div>
        <a-modal v-model:visible="showAddPlanModal" :footer="null" :width="520" centered wrapClassName="add-plan-modal" :bodyStyle="{ paddingBottom: '32px' }" @cancel="() => (showAddPlanModal = false)">
          <div class="add-plan-modal-header">
            <Icon icon="ant-design:form-outlined" style="font-size: 28px; color: #1890ff; margin-bottom: 8px" />
            <div class="add-plan-title">添加跟进计划</div>
            <div class="add-plan-divider"></div>
          </div>
          <a-form :model="addPlanForm" layout="vertical" class="add-plan-form">
            <a-form-item label="跟进计划信息" name="title">
              <a-textarea v-model:value="addPlanForm.title" placeholder="请输入计划内容" class="add-plan-textarea" :rows="6" :auto-size="{ minRows: 6, maxRows: 12 }" />
              <div class="add-plan-tip">请填写本次跟进的主要内容</div>
            </a-form-item>
            <div class="add-plan-btns">
              <a-button @click="handleCancelAddPlan" class="add-plan-cancel-btn">取消</a-button>
              <a-button type="primary" @click="handleAddPlanOk" class="add-plan-ok-btn">确 定</a-button>
            </div>
          </a-form>
        </a-modal>
        <!-- 文件上传模态框 -->
        <a-modal v-model:visible="showFileUploadModal" title="上传跟进计划文件" :width="600" :footer="null" @cancel="() => (showFileUploadModal = false)">
          <div class="file-upload-container">
            <a-upload-dragger
              v-model:fileList="fileUploadList"
              :multiple="true"
              :showUploadList="{
                showPreviewIcon: true,
                showRemoveIcon: true,
                showDownloadIcon: true,
              }"
              name="file"
              :headers="{ 'X-Access-Token': userStore.getToken }"
              :before-upload="handleBeforeUploadFile"
              :customRequest="customUploadFile"
              @remove="handleRemoveFile"
            >
              <p class="ant-upload-drag-icon">
                <Icon icon="ant-design:cloud-upload-outlined" style="font-size: 40px; color: #40a9ff" />
              </p>
              <p class="ant-upload-text">点击或拖拽文件到此处上传</p>
              <p class="ant-upload-hint">支持多文件上传，单个文件不超过10M</p>
            </a-upload-dragger>

            <div class="file-upload-actions">
              <a-button @click="() => (showFileUploadModal = false)">关闭</a-button>
              <a-button type="primary" @click="handleFileUploadComplete">完成</a-button>
            </div>
          </div>
        </a-modal>
        <JVxeTable keep-source resizable ref="followPlan" :loading="followPlanTable.loading" :columns="followPlanTableColumns" :dataSource="followPlanTable.dataSource" :height="340" :disabled="formDisabled" :rowNumber="true" :rowSelection="true" :toolbar="true">
          <template #followPlanFile="{ row }">
            <a-button type="primary" size="small" @click="showFileDetailModal(row.files, 'followPlan')" v-if="row.files && row.files.length > 0">
              文件详情
            </a-button>
            <span v-else>-</span>
          </template>
          <template #followPlanAction="{ row }">
            <a-space v-if="!formDisabled">
              <a-button type="link" size="small" @click="handleUploadPlanFile(row)">
                <Icon icon="ant-design:upload-outlined" style="margin-right: 4px" />
                上传文件
              </a-button>
              <a-button type="link" size="small" danger @click="handleDeleteFollowPlan(row)">
                <Icon icon="ant-design:delete-outlined" style="margin-right: 4px" />
                删除
              </a-button>
            </a-space>
          </template>
        </JVxeTable>
      </template>
      <template v-else-if="activeKey == 'followUpContent'">
        <div class="btn-row-flex">
          <template v-if="!formDisabled">
            <a-button type="primary" @click="showAddRecordModal = true" style="height: 32px; border-radius: 8px; box-shadow: 0 2px 8px #e6f7ff">新增跟进内容</a-button>
            <a-button type="primary" @click="MainTableSubmit()" style="height: 32px">确认</a-button>
          </template>
        </div>
        <a-modal v-model:visible="showAddRecordModal" :footer="null" :width="520" centered wrapClassName="add-plan-modal" :bodyStyle="{ paddingBottom: '32px' }" @cancel="() => (showAddRecordModal = false)">
          <div class="add-plan-modal-header">
            <Icon icon="ant-design:form-outlined" style="font-size: 28px; color: #1890ff; margin-bottom: 8px" />
            <div class="add-plan-title">添加跟进记录</div>
            <div class="add-plan-divider"></div>
          </div>
          <a-form :model="addRecordForm" layout="vertical" class="add-plan-form">
            <a-form-item label="客户标签" name="customerClassification">
              <a-select v-model:value="addRecordForm.customerClassification" placeholder="请选择客户标签" class="add-plan-input">
                <a-select-option v-for="item in customerClassificationOptions" :key="item.value" :value="item.value">
                  {{ item.label }}
                </a-select-option>
              </a-select>
            </a-form-item>
            <a-form-item label="跟进内容" name="content">
              <a-input v-model:value="addRecordForm.content" placeholder="请输入跟进内容" class="add-plan-input" />
            </a-form-item>
            <a-form-item label="跟进进度" name="progress">
              <a-input v-model:value="addRecordForm.progress" placeholder="请输入跟进进度" class="add-plan-input" />
            </a-form-item>
            <a-form-item label="跟进时间" name="followUpTime">
              <a-date-picker v-model:value="addRecordForm.followUpTime" style="width: 100%; height: 44px; border-radius: 8px; font-size: 16px" />
            </a-form-item>
            <div class="add-plan-btns">
              <a-button @click="handleCancelAddRecord" class="add-plan-cancel-btn">取消</a-button>
              <a-button type="primary" @click="handleAddRecordOk" class="add-plan-ok-btn">确 定</a-button>
            </div>
          </a-form>
        </a-modal>
        <!-- 跟进记录文件上传模态框 -->
        <a-modal v-model:visible="showRecordFileUploadModal" title="上传跟进记录文件" :width="600" :footer="null" @cancel="() => (showRecordFileUploadModal = false)">
          <div class="file-upload-container">
            <a-upload-dragger
              v-model:fileList="fileRecordUploadList"
              :multiple="true"
              :showUploadList="{
                showPreviewIcon: true,
                showRemoveIcon: true,
                showDownloadIcon: true,
              }"
              name="file"
              :headers="{ 'X-Access-Token': userStore.getToken }"
              :before-upload="handleBeforeUploadFile"
              :customRequest="customUploadRecordFile"
              @remove="handleRemoveFile"
            >
              <p class="ant-upload-drag-icon">
                <Icon icon="ant-design:cloud-upload-outlined" style="font-size: 40px; color: #40a9ff" />
              </p>
              <p class="ant-upload-text">点击或拖拽文件到此处上传</p>
              <p class="ant-upload-hint">支持多文件上传，单个文件不超过10M</p>
            </a-upload-dragger>

            <div class="file-upload-actions">
              <a-button @click="() => (showRecordFileUploadModal = false)">关闭</a-button>
              <a-button type="primary" @click="handleRecordFileUploadComplete">完成</a-button>
            </div>
          </div>
        </a-modal>
        <JVxeTable
          keep-source
          resizable
          ref="followUpContent"
          :loading="followUpContentTable.loading"
          :columns="followUpContentTableColumns"
          :dataSource="followUpContentTable.dataSource"
          :height="340"
          :disabled="formDisabled"
          :rowNumber="true"
          :rowSelection="true"
          :editConfig="{ trigger: 'click', mode: 'cell', showStatus: true }"
          :editRules="{}"
        >
          <template #followUpContentFile="{ row }">
            <a-button type="primary" size="small" @click="showFileDetailModal(row.files, 'followUpContent')" v-if="row.files && row.files.length > 0">
              文件详情
            </a-button>
            <span v-else>-</span>
          </template>
          <template #followUpContentAction="{ row }">
            <a-space v-if="!formDisabled">
              <a-button type="link" size="small" @click="handleUploadRecordFile(row)">
                <Icon icon="ant-design:upload-outlined" style="margin-right: 4px" />
                上传文件
              </a-button>
              <a-button type="link" size="small" danger @click="handleDeleteFollowUpContent(row)">
                <Icon icon="ant-design:delete-outlined" style="margin-right: 4px" />
                删除
              </a-button>
            </a-space>
          </template>
        </JVxeTable>
      </template>
    </div>

    <FileDetailModal
      v-model:visible="fileDetailModalVisible"
      :files="currentFiles"
      :disabled="formDisabled"
      :fileOrigin="fileDetailOrigin"
      @preview="handlePreviewFileFromDetail"
      @download="handleDownloadFileFromDetail"
      @delete="handleDeleteFileFromDetail"
      @update:visible="fileDetailModalVisible = $event"
    />
  </BasicModal>
</template>

<script lang="ts" setup>
import { ref, computed, unref, reactive, onMounted, watch, nextTick, h, Ref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { BasicForm, useForm, FormActionType } from '/@/components/Form/index';
import { JVxeTable } from '/@/components/jeecg/JVxeTable';
import { useJvxeMethod } from '/@/hooks/system/useJvxeMethods';
import { formSchema, followPlanColumns, followUpContentColumns } from '../FollowUp.data';
import { saveOrUpdate, followPlanList, followUpContentList, getFollowPlanFiles, getFollowUpFiles, deleteFile, uploadFollowPlanFile, uploadFollowUpFile } from '../FollowUp.api';
import { VALIDATE_FAILED } from '/@/utils/common/vxeUtils';
import { message, Modal } from 'ant-design-vue';
import { useUserStoreWithOut } from '/@/store/modules/user';
import { defHttp } from '/@/utils/http/axios';
import { Icon } from '/@/components/Icon';
import FileDetailModal from './FileDetailModal.vue';
// API接口常量
const API_ENDPOINTS = {
  DELETE_FOLLOW_PLAN: '/followup/followUp/deleteFollowPlan',
  DELETE_FOLLOW_UP_CONTENT: '/followup/followUp/deleteFollowUpContent',
};
// Emits声明
const emit = defineEmits(['register', 'success']);
const isUpdate = ref(true);
const formDisabled = ref(false);
const modalRef = ref();
const refKeys = ref(['followUp', 'followPlan', 'followUpContent']);
const tabNav = ref<any>([
  { tableName: 'followUp', tableTxt: '客户跟进表' },
  { tableName: 'followPlan', tableTxt: '跟进计划信息' },
  { tableName: 'followUpContent', tableTxt: '跟进记录信息' },
]);
const activeKey = ref('followUp');
const followPlan = ref();
const followUpContent = ref();
const tableRefs = { followPlan, followUpContent };

// 动态弹窗宽度计算
const modalWidth = computed(() => {
  if ((activeKey.value === 'followPlan' || activeKey.value === 'followUpContent') && !formDisabled.value) {
    return 900; // 编辑弹窗时宽度统一
  }
  if (formDisabled.value && (activeKey.value === 'followPlan' || activeKey.value === 'followUpContent')) {
    return 800; // 详情弹窗时宽度缩小
  }
  switch (activeKey.value) {
    case 'followPlan':
    case 'followUpContent':
      return 1200; // 其它情况宽
    default:
      return 800; // 主表单页面使用标准宽度
  }
});
const followPlanTable = reactive({
  loading: false,
  dataSource: [] as any[],
  columns: followPlanColumns,
});
const followUpContentTable = reactive({
  loading: false,
  dataSource: [] as any[],
  columns: followUpContentColumns,
});
// 详情模式下过滤操作栏
const followPlanTableColumns = computed(() => {
  if (!formDisabled.value) {
    // 编辑时隐藏"跟进计划ID"、"更新人"、"更新时间"、"逻辑删除标志"
    return followPlanTable.columns.filter((col) => !['followPlanId', 'updateBy', 'updateTime', 'isDeleted'].includes(col.key));
  }
  // 详情时隐藏"跟进计划ID"、"更新人"、"更新时间"、"操作"
  return followPlanTable.columns.filter((col) => !['followPlanId', 'updateBy', 'updateTime', 'isDeleted', 'action'].includes(col.key) && col.title !== '操作');
});
const followUpContentTableColumns = computed(() => {
  if (!formDisabled.value) {
    // 编辑时隐藏"跟进记录ID"、"创建日期"
    return followUpContentTable.columns.filter((col) => !['followUpContentId', 'createTime', 'isDeleted'].includes(col.key));
  }
  // 详情时隐藏"跟进记录ID"、"创建日期"、"操作"
  return followUpContentTable.columns.filter((col) => !['followUpContentId', 'createTime', 'isDeleted', 'action'].includes(col.key) && col.title !== '操作');
});
const showAddPlanModal = ref(false);
const addPlanForm = ref({
  title: '',
  fileList: [] as any[],
});
const showAddRecordModal = ref(false);
const addRecordForm = ref({
  customerClassification: '',
  content: '',
  progress: '',
  followUpTime: '',
  fileList: [] as any[],
});
// 文件上传相关变量
const showFileUploadModal = ref(false);
const fileUploadList = ref([]);
const currentUploadPlanId = ref('');
const showRecordFileUploadModal = ref(false);
const fileRecordUploadList = ref([]);
const currentUploadRecordId = ref('');
interface ClassificationOption {
  value: string;
  label: string;
}
const customerClassificationOptions = ref<ClassificationOption[]>([]);

// 跟进记录编辑状态管理
const editingFollowUpContentId = ref<string | null>(null);
const editingFollowUpContentData = ref<any>({});

// 预览相关状态
const showPreviewModal = ref(false);
const previewData = ref({
  title: '',
  content: '',
  fileUrl: '',
  fileType: '',
  fileName: '',
});

// 文件详情弹窗
const fileDetailModalVisible = ref(false);
const currentFiles = ref<any[]>([]);
const fileDetailOrigin = ref<'followPlan' | 'followUpContent' | null>(null);

function showFileDetailModal(files: any[], origin: 'followPlan' | 'followUpContent') {
  console.log('Files passed to detail modal:', JSON.stringify(files, null, 2));
  currentFiles.value = files;
  fileDetailOrigin.value = origin;
  fileDetailModalVisible.value = true;
}
//表单配置
const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({
  labelWidth: 150,
  schemas: formSchema,
  showActionButtonGroup: false,
  baseColProps: { span: 24 },
});
//表单赋值
const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
  //重置表单
  await reset();
  setModalProps({ confirmLoading: false, showCancelBtn: data?.showFooter, showOkBtn: data?.showFooter });
  isUpdate.value = !!data?.isUpdate;
  formDisabled.value = !data?.showFooter;
  if (unref(isUpdate)) {
    //表单赋值
    await setFieldsValue({
      ...data.record,
    });
    // 获取子表数据并处理文件名
    // 加载跟进计划数据和文件信息
    requestSubTableData(followPlanList, { id: data?.record?.id }, followPlanTable, async () => {
      await nextTick();
      const plans = followPlanTable.dataSource;
      for (const plan of plans) {
        const files = await getFollowPlanFiles(plan.id);
        console.log('获取到的跟进计划表信息 ' + plan.followPlanId + ':', JSON.stringify(files, null, 2));
        plan.files = files;
      }
      // 强制重新赋值数据源以触发响应式更新
      followPlanTable.dataSource = [...plans];
      await nextTick();
    });

    // 加载跟进记录数据和文件信息
    requestSubTableData(followUpContentList, { id: data?.record?.id }, followUpContentTable, async () => {
      await nextTick();
      const contents = followUpContentTable.dataSource;
      for (const content of contents) {
        const files = await getFollowUpFiles(content.id);
        content.files = files;
      }
      // 强制重新赋值数据源以触发响应式更新
      followUpContentTable.dataSource = [...contents];
      await nextTick();
    });
  }
  // 隐藏底部时禁用整个表单
  setProps({ disabled: !data?.showFooter });
  // 假设主表记录 id 字段为 id 或 followUpId
  currentFollowUpId.value = data?.record?.id || data?.record?.followUpId || '';
});
//方法配置
const jvxeMethods = useJvxeMethod(requestAddOrEdit, classifyIntoFormData, tableRefs, activeKey, refKeys);
const handleChangeTabs = jvxeMethods[0];
const handleSubmit = jvxeMethods[1];
const requestSubTableData = jvxeMethods[2] as (...args: any[]) => void;
const formRef = jvxeMethods[3] as Ref<FormActionType>;
// 弹窗tabs滚动区域的高度
const tabsStyle = computed(() => {
  let height: Nullable<string> = null;
  let minHeight = '100px';
  let maxHeight: Nullable<string> = '500px';
  // 弹窗wrapper
  let modalWrapperRef = modalRef.value?.modalWrapperRef;
  if (modalWrapperRef) {
    if (modalWrapperRef.fullScreen) {
      height = 'calc(' + modalWrapperRef.spinStyle.height + ' - 50px)';
      maxHeight = null;
    }
  }
  let overflow = 'auto';
  return { height, minHeight, maxHeight, overflow };
});
//设置标题
const title = computed(() => (!unref(isUpdate) ? '新增' : !unref(formDisabled) ? '编辑' : '详情'));

// 计算表格是否可编辑
const isTableEditable = computed(() => {
  return !unref(formDisabled) && unref(editingFollowUpContentId) !== null;
});
//重置
async function reset() {
  await resetFields();
  activeKey.value = 'followUp';
  followPlanTable.dataSource = [];
  followUpContentTable.dataSource = [];
}
function classifyIntoFormData(allValues) {
  let main = Object.assign({}, allValues.formValue);
  return {
    ...main, // 展开
    followPlanList: allValues.tablesValue[0].tableData,
    followUpContentList: allValues.tablesValue[1].tableData,
  };
}
//表单提交事件
async function requestAddOrEdit(values) {
  try {
    setModalProps({ confirmLoading: true });
    //提交表单
    await saveOrUpdate(values, isUpdate.value);
    //关闭弹窗
    closeModal();
    //刷新列表
    emit('success');
  } finally {
    setModalProps({ confirmLoading: false });
  }
}
// 用于缓存当前主表的 followUpId
const currentFollowUpId = ref('');

// 监听activeKey变化，动态调整弹窗大小
watch(activeKey, async (newKey) => {
  // 等待DOM更新后重新调整弹窗大小
  await nextTick();
  if (modalRef.value && modalRef.value.redoModalHeight) {
    modalRef.value.redoModalHeight();
  }
});

// 工具函数：显示确认对话框
function showConfirmDialog(title, content) {
  return new Promise((resolve) => {
    Modal.confirm({
      title,
      content,
      onOk: () => resolve(true),
      onCancel: () => resolve(false),
    });
  });
}

/**
 * 处理上传跟进计划文件
 * @param {Object} row - 当前行数据
 */
function handleUploadPlanFile(row: any) {
  if (!row.id) {
    message.error('跟进计划ID不能为空');
    return;
  }

  // 设置当前上传的计划ID
  currentUploadPlanId.value = row.id;

  // 清空文件列表
  fileUploadList.value = [];

  // 显示上传模态框
  showFileUploadModal.value = true;
}

/**
 * 文件上传前检查
 */
function handleBeforeUploadFile(file: File) {
  // 检查文件大小（10MB）
  const isLt10M = file.size / 1024 / 1024 < 10;
  if (!isLt10M) {
    message.error('文件必须小于10MB!');
    return false;
  }

  return true;
}

/**
 * 自定义文件上传
 */
function customUploadFile({ file, onProgress, onSuccess, onError }: any) {
  if (!currentUploadPlanId.value) {
    message.error('未获取到跟进计划ID');
    return;
  }

  const formData = new FormData();
  formData.append('file', file);
  formData.append('followPlanId', currentUploadPlanId.value);

  uploadFollowPlanFile(formData, (progressEvent) => {
    const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total);
    onProgress({ percent });
  })
    .then((res) => {
      onSuccess(res, null);
    })
    .catch((err) => {
      onError(err);
    });
}

/**
 * 文件上传完成并刷新列表
 */
async function handleFileUploadComplete() {
  showFileUploadModal.value = false;
  followPlanTable.loading = true;
  try {
    // 刷新跟进计划列表
    await requestSubTableData(followPlanList, { id: currentFollowUpId.value }, followPlanTable, async () => {
      await nextTick();
      const plans = followPlanTable.dataSource;
      for (const plan of plans) {
        const files = await getFollowPlanFiles(plan.id);
        console.log(`更新跟进计划 ${plan.id} 的文件信息:`, files);
        // 直接修改对象属性
        plan.files = files;
      }
      // 强制重新赋值数据源以触发响应式更新
      followPlanTable.dataSource = [...plans];
      await nextTick();
    });
    message.success('文件上传完成');
  } catch (error) {
    console.error("刷新文件列表失败", error);
    message.error('文件列表刷新失败');
  } finally {
    followPlanTable.loading = false;
  }
}

/**
 * 处理上传跟进记录文件
 * @param {Object} row - 当前行数据
 */
function handleUploadRecordFile(row: any) {
  if (!row.id) {
    message.error('跟进记录ID不能为空');
    return;
  }
  currentUploadRecordId.value = row.id;
  fileRecordUploadList.value = [];
  showRecordFileUploadModal.value = true;
}

/**
 * 自定义跟进记录文件上传
 */
function customUploadRecordFile({ file, onProgress, onSuccess, onError }: any) {
  if (!currentUploadRecordId.value) {
    message.error('未获取到跟进记录ID');
    return;
  }

  const formData = new FormData();
  formData.append('file', file);
  formData.append('followUpContentId', currentUploadRecordId.value);

  uploadFollowUpFile(formData, (progressEvent) => {
    const percent = Math.round((progressEvent.loaded * 100) / progressEvent.total);
    onProgress({ percent });
  })
    .then((res) => {
      onSuccess(res, null);
      message.success('文件上传成功');
    })
    .catch((err) => {
      onError(err);
    });
}

/**
 * 跟进记录文件上传完成并刷新列表
 */
async function handleRecordFileUploadComplete() {
  showRecordFileUploadModal.value = false;
  followUpContentTable.loading = true;
  try {
    await requestSubTableData(followUpContentList, { id: currentFollowUpId.value }, followUpContentTable, async () => {
      await nextTick();
      const contents = followUpContentTable.dataSource;
      for (const content of contents) {
        const files = await getFollowUpFiles(content.id);
        console.log(`更新跟进记录 ${content.id} 的文件信息:`, files);
        // 直接修改对象属性
        content.files = files;
      }
      // 强制重新赋值数据源以触发响应式更新
      followUpContentTable.dataSource = [...contents];
      await nextTick();
    });
    message.success('文件上传完成，列表已刷新');
  } catch (error) {
    console.error("刷新文件列表失败", error);
    message.error('文件列表刷新失败');
  } finally {
    followUpContentTable.loading = false;
  }
}

async function handleAddPlanOk() {
  try {
    // 校验表单
    if (!addPlanForm.value.title) {
      message.warning('请添加跟进计划');
      return;
    }
    // 获取 followUpId
    const followUpId = currentFollowUpId.value;
    if (!followUpId) {
      message.error('未获取到主表 followUpId');
      return;
    }
    // 组装参数
    const params = new FormData();
    params.append('followUpId', followUpId);
    params.append('followUpText', addPlanForm.value.title);
    params.append('followPlanId', '');
    console.log('调用 /followup/followUp/addFollowPlan 参数:', {
      followUpId,
      followUpText: addPlanForm.value.title,
      followPlanId: '',
    });
    // 调用后端接口
    const res = await defHttp.post({
      url: '/followup/followUp/addFollowPlan',
      params,
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    console.log('接口返回:', res);
    showAddPlanModal.value = false;
    Object.keys(addPlanForm.value).forEach((k) => (addPlanForm.value[k] = ''));
    emit('success');

    // 刷新跟进计划信息表数据
    await requestSubTableData(followPlanList, { id: followUpId }, followPlanTable, async () => {
      await nextTick();
      const plans = followPlanTable.dataSource;
      for (const plan of plans) {
        const files = await getFollowPlanFiles(plan.id);
        plan.files = files;
      }
      // 强制重新赋值数据源以触发响应式更新
      followPlanTable.dataSource = [...plans];
      await nextTick();
    });
    if (followPlan.value) {
      followPlan.value.reloadData();
    }
  } catch (err) {
    console.error('添加跟进计划失败:', err);
  }
}
// 获取当前用户信息
const userStore = useUserStoreWithOut();
const token = computed(() => userStore.getToken);

async function handleAddRecordOk() {
  try {
    if (!addRecordForm.value.customerClassification || !addRecordForm.value.content || !addRecordForm.value.progress) {
      const err = {
        customerClassification: !addRecordForm.value.customerClassification ? '客户标签未填写' : undefined,
        content: !addRecordForm.value.content ? '跟进内容未填写' : undefined,
        progress: !addRecordForm.value.progress ? '跟进进度未填写' : undefined,
      };
      console.error('表单校验失败:', err);
      message.warning('请填写完整内容');
      return;
    }
    const followUpId = currentFollowUpId.value;
    const customerClassification = addRecordForm.value.customerClassification;
    const content = addRecordForm.value.content;
    const progress = addRecordForm.value.progress;
    // 跟进时间自动生成
    const dayjs = (await import('dayjs')).default;
    const followUpTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
    const followUpContentId = '';
    const params = new FormData();
    params.append('followUpId', followUpId);
    params.append('customerClassification', customerClassification || '');
    params.append('followUpContent', content || '');
    params.append('progress', progress || '');
    params.append('followUpTime', followUpTime || '');
    params.append('followUpContentId', followUpContentId || '');
    console.log('调用 /followup/followUp/addFollowUpContent 参数:', {
      followUpId,
      customerClassification,
      followUpContent,
      progress,
      followUpTime,
      followUpContentId,
    });
    const res = await defHttp.post({
      url: '/followup/followUp/addFollowUpContent',
      params,
      headers: { 'Content-Type': 'multipart/form-data' },
    });
    console.log('接口返回:', res);
    showAddRecordModal.value = false;
    Object.keys(addRecordForm.value).forEach((k) => (addRecordForm.value[k] = ''));
    emit('success');

    // 刷新跟进记录信息表数据
    await requestSubTableData(followUpContentList, { id: followUpId }, followUpContentTable, async () => {
      await nextTick();
      const contents = followUpContentTable.dataSource;
      for (const content of contents) {
        const files = await getFollowUpFiles(content.id);
        content.files = files;
      }
      // 强制重新赋值数据源以触发响应式更新
      followUpContentTable.dataSource = [...contents];
      await nextTick();
    });
  } catch (err) {
    console.error('添加跟进记录失败:', err);
  }
}

onMounted(async () => {
  try {
    const res = await defHttp.get({ url: '/sys/dict/getDictItems/customer_classification' });
    // 假设返回 [{ value: 'A', text: 'A类客户' }, ...]
    customerClassificationOptions.value = Array.isArray(res)
      ? res.map((item) => ({
          value: item.value,
          label: item.text || item.label || item.value,
        }))
      : [];
  } catch (e) {
    customerClassificationOptions.value = [];
    console.error('客户标签字典获取失败', e);
  }
});

// 新增：主表专用提交方法
async function MainTableSubmit() {
  try {
    setModalProps({ confirmLoading: true });
    // 获取主表表单内容
    const mainValues = await formRef.value.validate();
    // 组装 FollowUp 实体参数
    const params = {
      id: mainValues.id || '',
      followUpId: mainValues.followUpId || '',
      customerId: mainValues.customerId || '',
      customerName: mainValues.customerName || '',
      principalId: mainValues.principalId || '',
      principalName: mainValues.principalName || '',
      group1: mainValues.group1 || '',
      group2: mainValues.group2 || '',
      isDeleted: mainValues.isDeleted || 0,
      createTime: mainValues.createTime || '',
    };
    console.log('MainTableSubmit 提交参数:', params);
    // 调用后端接口
    await defHttp.post({ url: '/followup/followUp/edit', params });
    closeModal();
    emit('success');
  } catch (err) {
    console.error('主表修改失败:', err);
  } finally {
    setModalProps({ confirmLoading: false });
  }
}

/**
 * 跟进计划修改方法
 * @param {Object} row - 当前行数据
 */
async function handleEditFollowPlan(row: any) {
  try {
    // 调试：输出完整的行数据
    console.log('跟进计划行数据:', row);
    // 文件预览相关变量
    const showFilePreviewModal = ref(false);
    const previewFileName = ref('');
    const previewFileUrl = ref('');
    const previewFileId = ref('');
    const isPreviewImage = ref(false);
    const isPreviewPdf = ref(false);

    // 跟进记录编辑状态管理
    const editingFollowUpContentId = ref<string | null>(null);
    const editingFollowUpContentData = ref<any>({});

    // 预览相关状态
    const showPreviewModal = ref(false);
    const previewData = ref({
      title: '',
      content: '',
      fileUrl: '',
      fileType: '',
      fileName: ''
    });
    //表单配置
    const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({
        labelWidth: 150,
        schemas: formSchema,
        showActionButtonGroup: false,
        baseColProps: {span: 24}
    });
     //表单赋值
    const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
        //重置表单
        await reset();
        setModalProps({confirmLoading: false,showCancelBtn:data?.showFooter,showOkBtn:data?.showFooter});
        isUpdate.value = !!data?.isUpdate;
        formDisabled.value = !data?.showFooter;
        // 新增：详情弹框时处理schema
        patchFormSchemaForDetail();
        if (unref(isUpdate)) {
            //表单赋值
            await setFieldsValue({
                ...data.record,
            });
            // 获取子表数据并处理文件名
            requestSubTableData(followPlanList, {id:data?.record?.id}, followPlanTable, () => {
              processFileNameInTable(followPlanTable.dataSource as any[], 'followPlanFile');
            });
            requestSubTableData(followUpContentList, {id:data?.record?.id}, followUpContentTable, () => {
              processFileNameInTable(followUpContentTable.dataSource as any[], 'followUpContent');
            });
        }
        // 隐藏底部时禁用整个表单
       setProps({ disabled: !data?.showFooter })
       // 假设主表记录 id 字段为 id 或 followUpId
       currentFollowUpId.value = data?.record?.id || data?.record?.followUpId || '';
    });
    //方法配置
    const jvxeMethods = useJvxeMethod(requestAddOrEdit, classifyIntoFormData, tableRefs, activeKey, refKeys);
    const handleChangeTabs = jvxeMethods[0];
    const handleSubmit = jvxeMethods[1];
    const requestSubTableData = jvxeMethods[2] as (...args: any[]) => void;
    const formRef = jvxeMethods[3];
    // 弹窗tabs滚动区域的高度
    const tabsStyle = computed(() => {
      let height: Nullable<string> = null
      let minHeight = '100px'
      let maxHeight: Nullable<string> = '500px'
      // 弹窗wrapper
      let modalWrapperRef = modalRef.value?.modalWrapperRef
      if (modalWrapperRef) {
        if (modalWrapperRef.fullScreen) {
          height = 'calc(' + modalWrapperRef.spinStyle.height + ' - 50px)';
          maxHeight = null
        }
      }
      let overflow = 'auto';
      return {height, minHeight, maxHeight, overflow};
    })
    //设置标题
    const title = computed(() => (!unref(isUpdate) ? '新增' : !unref(formDisabled) ? '编辑' : '详情'));

    // 参数验证
    if (!row.id) {
      message.error('跟进计划ID不能为空');
      return;
    }

    // 添加确认对话框
    const confirmed = await showConfirmDialog('确认修改', '确定要修改这条跟进计划吗？');

    if (!confirmed) return;

    // 显示加载状态
    setModalProps({ confirmLoading: true });

    // 获取当前用户信息
    const currentUser = userStore.getUserInfo;
    console.log('当前用户信息:', currentUser);

    // 获取当前时间
    const dayjs = (await import('dayjs')).default;
    const currentTime = dayjs().format('YYYY-MM-DD HH:mm:ss');

    // 这里可以打开修改弹窗，或者直接调用接口
    // 暂时先调用接口，后续可以优化为弹窗形式
        const params = {
          id: row.id, // 使用row.id作为主键
          followPlanId: row.id, // 使用row.id作为followPlanId
          followUpId: currentFollowUpId.value,
          followUpText: row.followUpText || '',
          fileName: row.followPlanFile || '',
          // 添加其他可能需要的字段
          isDeleted: row.isDeleted || 0,
          createTime: row.createTime || '',
          updateTime: currentTime, // 使用当前时间
          updateBy: (currentUser?.id || currentUser?.userId || currentUser?.username || currentUser?.realname) ?? 'system', // 使用当前用户ID
        };
    console.log('修改跟进计划参数:', params);
    await defHttp.post({ url: '/followup/followUp/editFollowPlan', data: params });
    message.success('跟进计划修改成功');
    // 刷新附表数据
    await requestSubTableData(followPlanList, { id: currentFollowUpId.value }, followPlanTable, async () => {
      await nextTick();
      const plans = followPlanTable.dataSource;
      for (const plan of plans) {
        const files = await getFollowPlanFiles(plan.id);
        plan.files = files;
      }
      // 强制重新赋值数据源以触发响应式更新
      followPlanTable.dataSource = [...plans];
      await nextTick();
    });
  } catch (err) {
    console.error('跟进计划修改失败:', err);
    const errorMsg = (err as any)?.response?.data?.message || (err as any)?.message || '跟进计划修改失败';
    message.error(errorMsg);
  } finally {
    setModalProps({ confirmLoading: false });
  }
}

/**
 * 跟进计划详情方法
 * @param {Object} row - 当前行数据
 */
function handleDetailFollowPlan(row: any) {
  try {
    // 参数验证
    if (!row.id) {
      message.error('跟进计划ID不能为空');
      return;
    }

    // 获取跟进计划详情
    defHttp
      .get({
        url: '/followup/followUp/getFollowPlanDetail',
        params: { id: row.id },
      })
      .then((res) => {
        if (res.success) {
          // 显示详情弹窗
          Modal.info({
            title: '跟进计划详情',
            width: 700,
            content: h('div', { class: 'plan-detail-container' }, [
              h('div', { class: 'plan-detail-item' }, [h('span', { class: 'plan-detail-label' }, '跟进计划信息:'), h('span', { class: 'plan-detail-value' }, row.followUpText || '无')]),
              h('div', { class: 'plan-detail-item' }, [h('span', { class: 'plan-detail-label' }, '跟进计划文件:'), h('span', { class: 'plan-detail-value' }, row.followPlanFile || '无')]),
              h('div', { class: 'plan-detail-item' }, [h('span', { class: 'plan-detail-label' }, '创建日期:'), h('span', { class: 'plan-detail-value' }, row.createTime || '无')]),
              h('div', { class: 'plan-detail-item' }, [h('span', { class: 'plan-detail-label' }, '更新人:'), h('span', { class: 'plan-detail-value' }, row.updateBy || '无')]),
              h('div', { class: 'plan-detail-item' }, [h('span', { class: 'plan-detail-label' }, '更新时间:'), h('span', { class: 'plan-detail-value' }, row.updateTime || '无')]),
            ]),
            okText: '关闭',
          });
        } else {
          message.error('获取跟进计划详情失败');
        }
      })
      .catch((err) => {
        console.error('获取跟进计划详情失败:', err);
        message.error('获取跟进计划详情失败');
      });
  } catch (err) {
    console.error('跟进计划详情查看失败:', err);
    message.error('跟进计划详情查看失败');
  }
}

/**
 * 跟进计划删除方法
 * @param {Object} row - 当前行数据
 */
async function handleDeleteFollowPlan(row: any) {
  console.log('删除跟进计划:', row);

  if (!row.id) {
    message.error('无法获取跟进计划ID，删除失败');
    return;
  }

  // 显示确认对话框
  const confirmed = await showConfirmDialog('确认删除', '确定要删除此跟进计划吗？');
  if (!confirmed) return;

  try {
    // 调用删除接口
    const result = await defHttp.delete({
      url: '/followup/followUp/deleteFollowPlan',
      params: { fileId: row.id },
    });

    console.log('删除跟进计划响应:', result);

    // 刷新数据
    await requestSubTableData(followPlanList, { id: currentFollowUpId.value }, followPlanTable, async () => {
      await nextTick();
      const plans = followPlanTable.dataSource;
      for (const plan of plans) {
        const files = await getFollowPlanFiles(plan.id);
        plan.files = files;
      }
      // 强制重新赋值数据源以触发响应式更新
      followPlanTable.dataSource = [...plans];
      await nextTick();
    });

    message.success('删除跟进计划成功');
  } catch (error) {
    console.error('删除跟进计划失败:', error);
    message.error('删除跟进计划失败');
  }
}

/**
 * 跟进记录修改方法 - 进入编辑模式
 * @param {Object} row - 当前行数据
 */
function handleEditFollowUpContent(row: any) {
  // 参数验证
  if (!row.id) {
    message.error('跟进记录ID不能为空');
    return;
  }

  // 进入编辑模式
  editingFollowUpContentId.value = row.id;
  editingFollowUpContentData.value = { ...row };

  message.info('已进入编辑模式，请修改数据后点击确认修改按钮');
}

/**
 * 跟进记录确认修改方法
 * @param {Object} row - 当前行数据
 */
async function handleConfirmEditFollowUpContent(row: any) {
  try {
    // 参数验证
    if (!row.id) {
      message.error('跟进记录ID不能为空');
      return;
    }

    // 添加确认对话框
    const confirmed = await showConfirmDialog('确认修改', '确定要保存这些修改吗？');

    if (!confirmed) return;

    // 显示加载状态
    setModalProps({ confirmLoading: true });

    // 获取当前用户信息
    const currentUser = userStore.getUserInfo;
    console.log('当前用户信息:', currentUser);

    // 获取当前时间
    const dayjs = (await import('dayjs')).default;
    const currentTime = dayjs().format('YYYY-MM-DD HH:mm:ss');

    const params: Record<string, any> = {
      id: row.id, // 使用id作为主键
      followUpContentId: row.id, // 使用row.id作为followUpContentId
      followUpId: currentFollowUpId.value,
      customerClassification: row.customerClassification || '',
      followUpContent: row.followUpContent || '',
      progress: row.progress || '',
      followUpTime: row.followUpTime || '',
      fileName: row.followUpContent || '',
      // 添加其他可能需要的字段
      isDeleted: row.isDeleted || 0,
      createTime: row.createTime || '',
      updateTime: currentTime, // 使用当前时间
      updateBy: (currentUser?.id || currentUser?.userId || currentUser?.username || currentUser?.realname) ?? 'system', // 使用当前用户ID
    };
    console.log('修改跟进记录参数:', params);
    await defHttp.post({ url: '/followup/followUp/editFollowUpContent', data: params });
    message.success('跟进记录修改成功');

    // 退出编辑模式
    editingFollowUpContentId.value = null;
    editingFollowUpContentData.value = {};

    // 刷新附表数据
    await requestSubTableData(followUpContentList, { id: currentFollowUpId.value }, followUpContentTable, async () => {
      await nextTick();
      const contents = followUpContentTable.dataSource;
      for (const content of contents) {
        const files = await getFollowUpFiles(content.id);
        content.files = files;
      }
      // 强制重新赋值数据源以触发响应式更新
      followUpContentTable.dataSource = [...contents];
      await nextTick();
    });
  } catch (err) {
    console.error('跟进记录修改失败:', err);
    const errorMsg = (err as any)?.response?.data?.message || (err as any)?.message || '跟进记录修改失败';
    message.error(errorMsg);
  } finally {
    setModalProps({ confirmLoading: false });
  }
}

/**
 * 跟进记录取消修改方法
 * @param {Object} row - 当前行数据
 */
function handleCancelEditFollowUpContent(row: any) {
  // 退出编辑模式
  editingFollowUpContentId.value = null;
  editingFollowUpContentData.value = {};

  message.info('已取消修改');
}

/**
 * 跟进记录删除方法
 * @param {Object} row - 当前行数据
 */
async function handleDeleteFollowUpContent(row: any) {
  try {
    // 参数验证
    if (!row.id) {
      message.error('跟进记录ID不能为空');
      return;
    }

    // 添加确认对话框
    const confirmed = await showConfirmDialog('确认删除', '确定要删除这条跟进记录吗？');

    if (!confirmed) return;

    // 显示加载状态
    setModalProps({ confirmLoading: true });

    const params = {
      followUpContentId: row.id, // 传入followUpContentId
    };
    console.log('删除跟进记录 - 行数据:', row);
    console.log('删除跟进记录 - 准备传入后端的数据:', params);
    await defHttp.post({ url: '/followup/followUp/deleteFollowUpContent', data: params });
    message.success('跟进记录删除成功');
    // 刷新附表数据
    await requestSubTableData(followUpContentList, { id: currentFollowUpId.value }, followUpContentTable, async () => {
      await nextTick();
      const contents = followUpContentTable.dataSource;
      for (const content of contents) {
        const files = await getFollowUpFiles(content.id);
        content.files = files;
      }
      // 强制重新赋值数据源以触发响应式更新
      followUpContentTable.dataSource = [...contents];
      await nextTick();
    });
  } catch (err) {
    console.error('跟进记录删除失败:', err);
    const errorMsg = (err as any)?.response?.data?.message || (err as any)?.message || '跟进记录删除失败';
    message.error(errorMsg);
  } finally {
    setModalProps({ confirmLoading: false });
  }
}

// 在文件上传相关的部分，修改文件列表渲染
function fileNameItemRender({ file, actions }: any) {
  // 获取文件名
  let name = '';
  let fileSize = '';
  let uploadTime = '';

  // 尝试从不同位置获取文件名
  if (file.name) {
    name = file.name;
  } else if (file.response && file.response.result) {
    // 如果是刚上传成功的文件，从响应中获取
    if (typeof file.response.result === 'string') {
      // 如果结果是字符串（文件路径），提取文件名
      name = file.response.result.split('/').pop();
    } else if (file.response.result.fileName) {
      // 如果结果是对象，直接获取文件名
      name = file.response.result.fileName;
    }
  } else if (file.url) {
    // 如果有URL，从URL中提取文件名
    name = file.url.split('/').pop();
  }

  // 获取文件大小
  if (file.size) {
    fileSize = formatFileSize(file.size);
  } else if (file.response && file.response.result && file.response.result.fileSize) {
    fileSize = formatFileSize(file.response.result.fileSize);
  }

  // 获取上传时间
  const now = new Date();
  uploadTime = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(
    now.getMinutes()
  ).padStart(2, '0')}:${String(now.getSeconds()).padStart(2, '0')}`;

  // 文件图标
  let fileIcon = '';
  const fileExtension = name.split('.').pop()?.toLowerCase();

  if (fileExtension) {
    if (['jpg', 'jpeg', 'png', 'gif', 'bmp'].includes(fileExtension)) {
      fileIcon = 'ant-design:file-image-outlined';
    } else if (fileExtension === 'pdf') {
      fileIcon = 'ant-design:file-pdf-outlined';
    } else if (['doc', 'docx'].includes(fileExtension)) {
      fileIcon = 'ant-design:file-word-outlined';
    } else if (['xls', 'xlsx'].includes(fileExtension)) {
      fileIcon = 'ant-design:file-excel-outlined';
    } else if (['ppt', 'pptx'].includes(fileExtension)) {
      fileIcon = 'ant-design:file-ppt-outlined';
    } else {
      fileIcon = 'ant-design:file-outlined';
    }
  } else {
    fileIcon = 'ant-design:file-outlined';
  }

  // 返回自定义渲染内容
  return h('div', { class: 'file-item-container' }, [
    // 文件图标
    h('div', { class: 'file-item-icon' }, [h(Icon, { icon: fileIcon, style: { fontSize: '24px', color: '#1890ff' } })]),
    // 文件信息
    h('div', { class: 'file-item-info' }, [
      h('div', { class: 'file-item-name' }, name),
      h('div', { class: 'file-item-meta' }, [
        fileSize && h('span', { class: 'file-item-size' }, fileSize),
        uploadTime && h('span', { class: 'file-item-time' }, uploadTime),
      ]),
    ]),
    // 操作按钮
    h('div', { class: 'file-item-actions' }, [actions.remove && h('span', { class: 'file-item-action' }, [actions.remove])]),
  ]);
}

// 格式化文件大小的辅助函数
function formatFileSize(size: number) {
  if (!size) return '';

  const units = ['B', 'KB', 'MB', 'GB', 'TB'];
  let index = 0;
  let fileSize = size;

  while (fileSize >= 1024 && index < units.length - 1) {
    fileSize /= 1024;
    index++;
  }

  return `${fileSize.toFixed(2)} ${units[index]}`;
}

// 处理表格数据中的文件路径为文件名
function processFileNameInTable(tableData: any[], fileKey: string) {
  if (Array.isArray(tableData)) {
    tableData.forEach((row) => {
      if (row[fileKey]) {
        row[fileKey] = row[fileKey].split('/').pop();
      }
    });
  }
}

// 文件上传前检查 - 跟进计划
function handleBeforeUploadPlan(file: any) {
  // 检查文件大小（10MB）
  const isLt10M = file.size / 1024 / 1024 < 10;
  if (!isLt10M) {
    message.error('文件必须小于10MB!');
    return false;
  }

  // 允许上传
  return true;
}

// 文件上传前检查 - 跟进记录
function handleBeforeUploadContent(file: any) {
  // 检查文件大小（10MB）
  const isLt10M = file.size / 1024 / 1024 < 10;
  if (!isLt10M) {
    message.error('文件必须小于10MB!');
    return false;
  }

  // 允许上传
  return true;
}

// 自定义上传 - 跟进计划
function customUploadPlan({
  file,
  onProgress,
  onSuccess,
  onError,
}: {
  file: File;
  onProgress: (event: { percent: number }) => void;
  onSuccess: (response: any, xhr: XMLHttpRequest) => void;
  onError: (error: any) => void;
}) {
  if (!currentFollowUpId.value) {
    message.error('请先保存跟进计划');
    return;
  }

  const formData = new FormData();
  formData.append('file', file);
  formData.append('followPlanId', currentFollowUpId.value);

  // 使用原生XMLHttpRequest上传
  const xhr = new XMLHttpRequest();

  // 设置进度回调
  xhr.upload.onprogress = (e) => {
    if (e.lengthComputable) {
      const percent = Math.round((e.loaded * 100) / e.total);
      onProgress({ percent });
    }
  };

  // 设置完成回调
  xhr.onload = () => {
    if (xhr.status >= 200 && xhr.status < 300) {
      try {
        const result = JSON.parse(xhr.responseText);
        onSuccess(result, xhr);

        // 显示上传成功提示
        const successMessage = result.message || '文件上传成功';
        message.success({
          content: successMessage,
          key: 'upload-success',
          duration: 2,
        });
      } catch (e) {
        onError({ status: xhr.status, method: 'post', url: '' });
      }
    } else {
      onError({ status: xhr.status, method: 'post', url: '' });
    }
  };

  // 设置错误回调
  xhr.onerror = () => {
    onError({ status: xhr.status, method: 'post', url: '' });
  };

  // 获取完整URL
  const baseUrl = import.meta.env.VITE_GLOB_API_URL || '';
  const url = `${baseUrl}/followup/followUp/uploadFollowPlanFile`;

  // 打开连接
  xhr.open('POST', url, true);

  // 添加认证头
  const userStore = useUserStoreWithOut();
  const token = userStore.getToken;
  if (token) {
    xhr.setRequestHeader('X-Access-Token', token);
  }

  // 发送请求
  xhr.send(formData);

  // 返回上传取消函数
  return {
    abort() {
      xhr.abort();
    },
  };
}

// 自定义上传 - 跟进记录
function customUploadContent({
  file,
  onProgress,
  onSuccess,
  onError,
}: {
  file: File;
  onProgress: (event: { percent: number }) => void;
  onSuccess: (response: any, xhr: XMLHttpRequest) => void;
  onError: (error: any) => void;
}) {
  if (!currentFollowUpId.value) {
    message.error('请先保存跟进记录');
    return;
  }

  const formData = new FormData();
  formData.append('file', file);
  formData.append('followUpContentId', currentFollowUpId.value);

  // 使用原生XMLHttpRequest上传
  const xhr = new XMLHttpRequest();

  // 设置进度回调
  xhr.upload.onprogress = (e) => {
    if (e.lengthComputable) {
      const percent = Math.round((e.loaded * 100) / e.total);
      onProgress({ percent });
    }
  };

  // 设置完成回调
  xhr.onload = () => {
    if (xhr.status >= 200 && xhr.status < 300) {
      try {
        const result = JSON.parse(xhr.responseText);
        onSuccess(result, xhr);

        // 显示上传成功提示
        const successMessage = result.message || '文件上传成功';
        message.success({
          content: successMessage,
          key: 'upload-success',
          duration: 2,
        });
      } catch (e) {
        onError({ status: xhr.status, method: 'post', url: '' });
      }
    } else {
      onError({ status: xhr.status, method: 'post', url: '' });
    }
  };

  // 设置错误回调
  xhr.onerror = () => {
    onError({ status: xhr.status, method: 'post', url: '' });
  };

  // 获取完整URL
  const baseUrl = import.meta.env.VITE_GLOB_API_URL || '';
  const url = `${baseUrl}/followup/followUp/uploadFollowUpContentFile`;

  // 打开连接
  xhr.open('POST', url, true);

  // 添加认证头
  const userStore = useUserStoreWithOut();
  const token = userStore.getToken;
  if (token) {
    xhr.setRequestHeader('X-Access-Token', token);
  }

  // 发送请求
  xhr.send(formData);

  // 返回上传取消函数
  return {
    abort() {
      xhr.abort();
    },
  };
}

/**
 * 文件下载（通过新接口）
 */
function handleDownloadFileFromDetail(file: any) {
  // 检查文件ID
  if (!file.id) {
    message.warning('未找到文件ID');
    return;
  }

  try {
    // 获取文件下载URL
    const baseUrl = import.meta.env.VITE_GLOB_API_URL || '';
    const timestamp = new Date().getTime();
    const token = userStore.getToken;
    const url = `${baseUrl}/followup/followUp/downloadFile?fileId=${file.id}&_t=${timestamp}&token=${token}`;

    // 创建下载链接
    const a = document.createElement('a');
    a.href = url;
    a.download = file.fileName || '文件';
    a.target = '_blank'; // 添加target属性，防止某些浏览器的跨域问题
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);

    console.log('文件下载请求已发送:', url);
  } catch (error) {
    console.error('文件下载失败:', error);
    message.error('文件下载失败，请稍后重试');
  }
}

/**
 * 文件预览（通过新接口）
 */
function handlePreviewFileFromDetail(file: any) {
  //检查文件ID
  if (!file.id) {
    message.warning('未找到文件ID');
    return;
  }

  try {
    // 获取文件预览URL
    const baseUrl = import.meta.env.VITE_GLOB_API_URL || '';
    const timestamp = new Date().getTime();
    const token = userStore.getToken;
    const url = `${baseUrl}/followup/followUp/previewFile?fileId=${file.id}&_t=${timestamp}&token=${token}`;

    // 打开预览窗口
    window.open(url, '_blank');

    console.log('文件预览请求已发送:', url);
  } catch (error) {
    console.error('文件预览失败:', error);
    message.error('文件预览失败，请稍后重试');
  }
}

/**
 * 文件删除（通用处理）
 */
async function handleDeleteFileFromDetail(file: any) {
  if (!file.id) {
    message.error('无法获取文件ID，删除失败');
    return;
  }

  Modal.confirm({
    title: '确认删除',
    content: '确定要删除此文件吗？',
    class: 'delete-confirm-modal',
    icon: h('span', { class: 'warning-icon' }, '!'),
    okText: '确定',
    cancelText: '取消',
    async onOk() {
      try {
        await deleteFile(file.id);
        message.success('文件删除成功');

        // 直接从当前文件列表中移除被删除的文件
        currentFiles.value = currentFiles.value.filter(item => item.id !== file.id);

        // 同时更新表格数据中的文件列表
        if (fileDetailOrigin.value === 'followPlan') {
          await requestSubTableData(followPlanList, { id: currentFollowUpId.value }, followPlanTable, async () => {
            await nextTick();
            const plans = followPlanTable.dataSource;
            for (const plan of plans) {
              const files = await getFollowPlanFiles(plan.id);
              console.log(`删除文件后更新跟进计划 ${plan.id} 的文件信息:`, files);
              plan.files = files;
            }
            // 强制重新赋值数据源以触发响应式更新
            followPlanTable.dataSource = [...plans];
            await nextTick();
          });
        } else if (fileDetailOrigin.value === 'followUpContent') {
          await requestSubTableData(followUpContentList, { id: currentFollowUpId.value }, followUpContentTable, async () => {
            await nextTick();
            const contents = followUpContentTable.dataSource;
            for (const content of contents) {
              const files = await getFollowUpFiles(content.id);
              console.log(`删除文件后更新跟进记录 ${content.id} 的文件信息:`, files);
              content.files = files;
            }
            // 强制重新赋值数据源以触发响应式更新
            followUpContentTable.dataSource = [...contents];
            await nextTick();
          });
        }

        // 如果文件列表为空，关闭文件详情弹窗
        if (currentFiles.value.length === 0) {
          fileDetailModalVisible.value = false;
        }
      } catch (error) {
        console.error('文件删除失败:', error);
        message.error('文件删除失败');
      }
    }
  });
}

/**
 * 处理添加跟进计划弹窗取消事件（调用 /followup/followUp/deleteFile）
 */
async function handleCancelAddPlan() {
  // 获取已上传的文件路径（只处理已上传成功的文件）
  const fileList = addPlanForm.value.fileList || [];
  // 使用类型断言解决类型问题
  const uploadedFiles = fileList.filter((f) => {
    const file = f as any;
    return file.status === 'done' && (file.response?.success || file.response?.code === 200);
  });

  if (uploadedFiles.length > 0) {
    try {
      // 遍历所有已上传的文件，逐个删除
      for (const fileObj of uploadedFiles) {
        // 使用类型断言
        const file = fileObj as any;
        // 获取文件ID，优先使用response中的id字段
        const fileId = file.response?.result?.id || file.response?.id;

        if (fileId) {
          console.log('准备删除文件, fileId:', fileId);
          await defHttp.delete({
            url: '/followup/followUp/deleteFile',
            params: { fileId: fileId }
          }); // 使用 defHttp.delete 调用 deleteFile，并确保fileId作为query参数传递
          console.log('文件删除成功, fileId:', fileId);
        } else {
          console.warn('无法获取文件ID，跳过删除');
        }
      }
    } catch (err) {
      console.error('文件删除失败', err);
    }
  }

  // 关闭弹窗并重置表单
  showAddPlanModal.value = false;
  Object.keys(addPlanForm.value).forEach((k) => (addPlanForm.value[k] = ''));
}

/**
 * 处理添加跟进记录弹窗取消事件（调用 /followup/followUp/deleteFile）
 */
async function handleCancelAddRecord() {
  // 获取已上传的文件路径（只处理已上传成功的文件）
  const fileList = addRecordForm.value.fileList || [];
  // 使用类型断言解决类型问题
  const uploadedFiles = fileList.filter((f) => {
    const file = f as any;
    return file.status === 'done' && (file.response?.success || file.response?.code === 200);
  });

  if (uploadedFiles.length > 0) {
    try {
      // 遍历所有已上传的文件，逐个删除
      for (const fileObj of uploadedFiles) {
        // 使用类型断言
        const file = fileObj as any;
        // 获取文件ID，优先使用response中的id字段
        const fileId = file.response?.result?.id || file.response?.id;

        if (fileId) {
          console.log('准备删除文件, fileId:', fileId);
          await defHttp.delete({
            url: '/followup/followUp/deleteFile',
            params: { fileId: fileId }
          }); // 使用 defHttp.delete 调用 deleteFile，并确保fileId作为query参数传递
          console.log('文件删除成功, fileId:', fileId);
        } else {
          console.warn('无法获取文件ID，跳过删除');
        }
      }
    } catch (err) {
      console.error('文件删除失败', err);
    }
  }

  // 关闭弹窗并重置表单
  showAddRecordModal.value = false;
  Object.keys(addRecordForm.value).forEach((k) => (addRecordForm.value[k] = ''));
}

/**
 * 处理删除文件
 */
function handleRemoveFile(file: any) {
  console.log('删除文件:', file);

  // 获取文件ID
  let fileId = '';

  // 从文件对象中获取信息
  if (file.response && file.response.result) {
    if (typeof file.response.result === 'object') {
      fileId = file.response.result.id || '';
    } else if (typeof file.response.result === 'string') {
      fileId = file.response.result;
    }
  } else if (file.id) {
    fileId = file.id;
  } else if (file.uid && file.status === 'done') {
    // 尝试从其他属性获取
    fileId = file.uid;
  }

  if (!fileId) {
    message.error('无法获取文件ID，删除失败');
    return false;
  }

  console.log('准备删除文件，fileId:', fileId);

  // 调用删除文件接口
  return new Promise<boolean>((resolve) => {
    Modal.confirm({
      title: '确认删除',
      content: '确定要删除此文件吗？',
      okText: '确定',
      cancelText: '取消',
      onOk: async () => {
        try {
          // 使用DELETE方法调用删除接口
          const result = await defHttp.delete({
            url: '/followup/followUp/deleteFile',
            params: { fileId },
          });

          console.log('删除文件响应:', result);

          message.success('文件删除成功');
          resolve(true);
        } catch (error) {
          console.error('文件删除失败:', error);
          message.error('文件删除失败');
          resolve(false);
        }
      },
      onCancel: () => {
        resolve(false);
      },
    });
  });
}

    // 新增：详情弹框时隐藏下拉/日历标志
    function patchFormSchemaForDetail() {
      if (formDisabled.value) {
        formSchema.forEach(item => {
          if (["group1", "group2", "createTime"].includes(item.field)) {
            if (!item.componentProps || typeof item.componentProps === 'function') item.componentProps = {};
            const props = item.componentProps as Record<string, any>;
            props.suffixIcon = null;
            if (item.component === "JDictSelectTag") {
              props.showArrow = false;
            }
            if (item.field === "createTime") {
              props.inputReadOnly = true;
              props.allowClear = false;
            }
            item.componentProps = props;
          }
        });
      }
    }
</script>

<style lang="less" scoped>
/** 时间和数字输入框样式 */
:deep(.ant-input-number) {
  width: 100%;
}

:deep(.ant-calendar-picker) {
  width: 100%;
}

.titleArea {
  display: flex;
  align-content: center;
  padding-right: 70px;
  .title {
    margin-right: 16px;
    line-height: 32px;
  }
  .right {
    overflow-x: auto;
    overflow-y: hidden;
    flex: 1;
    white-space: nowrap;
    .ant-radio-group {
      font-weight: normal;
    }
  }
}

html[data-theme='light'] {
  .right {
    .ant-radio-group {
      :deep(.ant-radio-button-wrapper:not(.ant-radio-button-wrapper-checked)) {
        color: #555;
      }
    }
  }
}

/** 编辑模式下的表格样式 */
:deep(.j-vxe-table) {
  .vxe-body--row {
    &.row--editing {
      background-color: #e6f7ff !important;
      border: 2px solid #1890ff !important;
    }
  }

  .vxe-cell--edit {
    background-color: #fff !important;
    border: 1px solid #1890ff !important;
  }
}

/* 文件上传列表样式 */
:deep(.file-item-container) {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  border-radius: 4px;
  background-color: #f9f9f9;
  margin-bottom: 8px;
  transition: all 0.3s;

  &:hover {
    background-color: #f0f0f0;
  }

  .file-item-icon {
    margin-right: 12px;
    display: flex;
    align-items: center;
  }

  .file-item-info {
    flex: 1;
    overflow: hidden;

    .file-item-name {
      font-size: 14px;
      color: #333;
      margin-bottom: 4px;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .file-item-meta {
      display: flex;
      font-size: 12px;
      color: #999;

      .file-item-size {
        margin-right: 12px;
      }

      .file-item-time {
        flex: 1;
      }
    }
  }

  .file-item-actions {
    margin-left: 12px;

    .file-item-action {
      color: #1890ff;
      cursor: pointer;

      &:hover {
        color: #40a9ff;
      }
    }
  }
}

.add-plan-modal .ant-modal-content {
  border-radius: 18px;
  box-shadow: 0 8px 32px rgba(24, 144, 255, 0.13);
  padding: 0 0 24px 0;
  background: #fafdff;
}
.add-plan-modal-header {
  text-align: center;
  padding: 32px 0 12px 0;
  background: linear-gradient(90deg, #e6f7ff 0%, #fff 100%);
  border-radius: 18px 18px 0 0;
}
.add-plan-title {
  font-size: 24px;
  font-weight: 700;
  color: #222;
  margin-bottom: 6px;
  letter-spacing: 1px;
}
.add-plan-divider {
  width: 48px;
  height: 4px;
  background: linear-gradient(90deg, #1890ff 0%, #40a9ff 100%);
  border-radius: 2px;
  margin: 0 auto 0 auto;
}
.add-plan-form {
  padding: 24px 18px 0 18px;
}
.add-plan-input {
  border-radius: 8px;
  height: 44px;
  font-size: 16px;
}
.add-plan-textarea {
  border-radius: 8px;
  font-size: 16px;
  resize: vertical;
  min-height: 120px;
}
.add-plan-tip {
  color: #bfbfbf;
  font-size: 12px;
  margin-top: 4px;
}
.add-plan-uploader {
  border-radius: 10px;
  border: 1.5px dashed #91d5ff;
  background: #f0faff;
  transition: border-color 0.3s;
  &:hover {
    border-color: #1890ff;
    background: #e6f7ff;
  }
  .ant-upload-drag-icon {
    margin-bottom: 8px;
  }
  .add-plan-upload-text {
    font-size: 16px;
    color: #1890ff;
    margin-bottom: 2px;
  }
  .add-plan-upload-hint {
    color: #bfbfbf;
    font-size: 12px;
  }
}
.add-plan-btns {
  text-align: center;
  margin-top: 18px;
  .add-plan-ok-btn,
  .add-plan-cancel-btn {
    border-radius: 20px;
    padding: 0 32px;
    font-size: 16px;
    height: 40px;
    min-width: 100px;
    box-sizing: border-box;
  }
  .add-plan-ok-btn {
    background: linear-gradient(90deg, #1890ff 0%, #40a9ff 100%);
    border: none;
    color: #fff;
  }
  .add-plan-cancel-btn {
    background: #f5f5f5;
    border: 1px solid #d9d9d9;
    color: #333;
    margin-right: 18px;
  }
}

// 操作按钮样式
:deep(.ant-btn-link) {
  padding: 4px 8px;
  border-radius: 4px;
  transition: all 0.3s;

  &:hover {
    background-color: #f0f0f0;
  }

  &.ant-btn-dangerous {
    &:hover {
      background-color: #fff2f0;
    }
  }
}

:deep(.ant-space) {
  .ant-btn {
    font-size: 12px;
    height: 24px;
    line-height: 22px;
  }
}
.btn-row-flex {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 0 0 8px 0;
}


/* 上传成功提示样式 */
:deep(.ant-message-success) {
  .ant-message-custom-content {
    display: flex;
    align-items: center;

    .anticon {
      font-size: 16px;
    }
  }
}

/* 详情弹窗样式 */
.plan-detail-container {
  padding: 16px;
}

.plan-detail-item {
  margin-bottom: 16px;
  display: flex;
}

.plan-detail-label {
  font-weight: 500;
  color: #333;
  width: 120px;
  flex-shrink: 0;
}

.plan-detail-value {
  color: #666;
  flex: 1;
}

/* 文件名显示样式 */
.file-name-display {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;

  span {
    max-width: 180px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .ant-space {
    flex-wrap: nowrap;

    .ant-btn {
      padding: 0 4px;
      height: 22px;
      line-height: 20px;
      font-size: 12px;
    }
  }
}
</style>

<style lang="less">
// Online表单Tab风格专属样式
.j-cgform-tab-modal {
  .contentArea {
    padding: 20px 1.5% 0;
  }

  //.ant-modal-header {
  //  padding-top: 8px;
  //  padding-bottom: 8px;
  //  border-bottom: none !important;
  //}

  .ant-modal .ant-modal-body > .scrollbar,
  .ant-tabs-nav .ant-tabs-tab {
    padding-top: 0;
  }

  .ant-tabs-top-bar {
    width: calc(100% - 55px);
    position: relative;
    left: -14px;
  }

  .ant-tabs .ant-tabs-top-content > .ant-tabs-tabpane {
    overflow: hidden auto;
  }
}

/* 文件上传组件样式 */
.add-plan-modal {
  .ant-upload-list-item {
    margin-top: 8px;
    padding: 8px;
    background-color: #f9f9f9;
    border-radius: 4px;
    border: 1px solid #f0f0f0;

    &:hover {
      background-color: #f0f0f0;
    }

    .ant-upload-list-item-name {
      color: #333;
      font-weight: 500;
    }

    .ant-upload-list-item-card-actions {
      .anticon {
        color: #ff4d4f;

        &:hover {
          color: #ff7875;
        }
      }
    }
  }

  .ant-upload-drag {
    border: 2px dashed #d9d9d9;
    background: #fafafa;
    border-radius: 8px;
    transition: all 0.3s;

    &:hover {
      border-color: #1890ff;
    }

    .ant-upload-drag-container {
      padding: 16px 0;
    }
  }
}

/* 文件上传容器样式 */
.file-upload-container {
  display: flex;
  flex-direction: column;
  gap: 16px;

  .file-upload-actions {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 16px;
  }
}

/* 文件预览容器样式 */
.file-preview-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 300px;

  .image-preview {
    width: 100%;
    display: flex;
    justify-content: center;

    img {
      max-width: 100%;
      max-height: 500px;
      object-fit: contain;
    }
  }

  .pdf-preview {
    width: 100%;
    height: 500px;

    iframe {
      border: none;
    }
  }

  .file-preview-fallback {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 40px 0;
    color: #666;
  }
}

/* 上传进度条样式 */
:deep(.ant-upload-list) {
  .ant-upload-list-item {
    .ant-upload-list-item-info {
      .ant-upload-list-item-card-actions {
        .anticon {
          color: rgba(0, 0, 0, 0.45);

          &:hover {
            color: #1890ff;
          }
        }
      }
    }

    .ant-upload-list-item-progress {
      padding-left: 4px;
      bottom: 14px;
      width: calc(100% - 24px);
    }
  }
}
</style>

<style lang="less">
/* 全局样式，应用于确认弹窗 */
.delete-confirm-modal {
  .ant-modal-content {
    border-radius: 8px;
    overflow: hidden;
  }
  
  .ant-modal-header {
    padding: 16px 24px;
    background-color: #fff;
    border-bottom: none;
  }
  
  .ant-modal-body {
    padding: 0 24px 24px;
  }
  
  .ant-modal-confirm-title {
    font-size: 16px;
    font-weight: 500;
    color: #333;
  }
  
  .ant-modal-confirm-content {
    margin-top: 8px;
    margin-left: 28px;
    font-size: 14px;
    color: #333;
  }
  
  .ant-modal-confirm-btns {
    margin-top: 24px;
    
    .ant-btn {
      min-width: 60px;
      height: 32px;
      border-radius: 4px;
    }
    
    .ant-btn-primary {
      background-color: #1890ff;
    }
  }
  
  .warning-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    background-color: #faad14;
    border-radius: 50%;
    color: white;
    font-weight: bold;
    font-size: 14px;
    margin-right: 8px;
    vertical-align: middle;
  }
}
</style>
